package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"user-center/src/common"
	"user-center/src/db"
	"user-center/src/model"
	"user-center/src/model/request"
	"user-center/src/model/response"
	"user-center/src/service"

	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
)

var errParseJsonRequestError = errors.New("解析参数错误")

func parsePostJsonRequest(ctx *gin.Context, req any) error {
	res := &response.BaseResponse{}
	data, _ := ctx.GetRawData()
	// 解析参数
	if err := json.Unmarshal(data, &req); err != nil {
		log.Errorf("request json err %v", err)
		res.ResponseWithError(common.PARAMS_ERROR, err.Error())
		ctx.JSON(http.StatusOK, res)
		return errParseJsonRequestError
	}
	return nil
}
func parseGetRequest(ctx *gin.Context, req any) error {
	//data, _ := ctx.GetRawData()
	valueType := reflect.TypeOf(req)
	// 输出接口的类型
	//fmt.Println("Type of value:", valueType)

	// 如果接口是指针类型，则解引用获取实际类型
	if valueType.Kind() == reflect.Ptr {
		valueType = valueType.Elem()
	}

	// 输出实际类型的字段信息
	if valueType.Kind() == reflect.Struct {
		for i := 0; i < valueType.NumField(); i++ {
			field := valueType.Field(i)
			//fmt.Println("Field Name:", field.Name)

			fieldValue := ctx.Query(strings.ToLower(field.Name[:1]) + field.Name[1:])
			//fmt.Println("Filed Value : ", fieldValue)
			// 处理有值字段
			if fieldValue != "" {
				fieldValueReflect := reflect.ValueOf(req).Elem().FieldByName(field.Name)
				switch fieldValueReflect.Kind() {
				case reflect.String:
					fieldValueReflect.SetString(fieldValue)
				case reflect.Int:
					value, err := strconv.Atoi(fieldValue)
					if err != nil {
						return err
					}
					fieldValueReflect.SetInt(int64(value))
				case reflect.Int64:
					value, err := strconv.ParseInt(fieldValue, 10, 64)
					if err != nil {
						return err
					}
					fieldValueReflect.SetInt(value)
				}
			}
		}
	}
	return nil
}

func pageNumAndSize(ctx *gin.Context) (pageNum, pageSize int) {
	pageSize, err := strconv.Atoi(ctx.Query("pageSize"))
	if err != nil {
		pageSize = 0
	}
	pageNum, err = strconv.Atoi(ctx.Query("pageNum"))
	if err != nil {
		pageNum = 0
	}
	return
}

// UserRegister
// @Tags        user
// @Summary     注册新用户
// @Description   注册新用户
// @Param Register body request.UserRegisterRequest true "Register"
// @Router /user/register [post]
func UserRegister(ctx *gin.Context) {
	req := &request.UserRegisterRequest{}
	res := &response.BaseResponse{}
	err := parsePostJsonRequest(ctx, req)
	if err != nil {
		return
	}
	if req.UserAccount == "" || req.UserPassword == "" || req.CheckPassword == "" {
		res.ResponseWithError(common.NULL_ERROR, "账号或密码为空")
		ctx.JSON(http.StatusOK, res)
		return
	}
	//处理请求
	res = service.Register(req, ctx)
	ctx.JSON(http.StatusOK, res)
}

// UserLogin
// @Tags        user
// @Summary     登录
// @Description   登录
// @Param Login body request.UserLoginRequest true "Login"
// @Router /user/login [post]
func UserLogin(ctx *gin.Context) {
	req := &request.UserLoginRequest{}
	res := &response.BaseResponse{}
	err := parsePostJsonRequest(ctx, req)
	if err != nil {
		return
	}
	if req.UserAccount == "" || req.UserPassword == "" {
		res.ResponseWithError(common.NULL_ERROR, "账号或密码为空")
		ctx.JSON(http.StatusOK, res)
		return
	}
	ctx.JSON(http.StatusOK, service.UserLogin(req, ctx))
}

// UserLogout
// @Tags        user
// @Summary     退出
// @Description   退出
// @Router /user/logout [post]
func UserLogout(ctx *gin.Context) {
	service.UserLogOut(ctx)
	ctx.JSON(http.StatusOK, response.BaseResponse{})
}

// UserGetCurrent
// @Tags        user
// @Summary     获取当前登录用户
// @Description   获取当前登录用户
// @Router /user/login [get]
func UserGetCurrent(ctx *gin.Context) {
	ctx.JSON(http.StatusOK, service.GetUserCurrent(ctx))
}

// UserInfo
// @Tags        user
// @Summary     查询用户信息
// @Description   一般自己查询别的用户信息
// @Param UserInfo query int true "UserInfo"
// @Router /user/info [get]
func UserInfo(ctx *gin.Context) {
	res := &response.BaseResponse{}
	userId, err := strconv.ParseInt(ctx.Query("userId"), 10, 64)
	if err != nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		ctx.JSON(http.StatusOK, res)
		return
	}

	ctx.JSON(http.StatusOK, service.UserInfo(ctx, userId))
}

// UserSearch
// @Tags        user
// @Summary     模糊查询用户
// @Description   仅供管理员查询
// @Param username query string true "username"
// @Router /user/search [get]
func UserSearch(ctx *gin.Context) {
	res := &response.BaseResponse{}
	username := ctx.Query("username")
	if !service.IsAdmin(ctx) {
		res.ResponseWithError(common.NO_AUTH, "无权限")
		ctx.JSON(http.StatusOK, res)
		return
	}

	ctx.JSON(http.StatusOK, service.UserSearch(username, ctx))

}

// UserSearchTags
// @Tags        user
// @Summary     根据tags查询用户
// @Description   根据tags查询用户
// @Param tagNameList query string false "tagNameList"
// @Router /user/search/tags [get]
func UserSearchTags(ctx *gin.Context) {
	res := &response.BaseResponse{}
	tagNameList := ctx.QueryArray("tagNameList")
	if tagNameList == nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		ctx.JSON(http.StatusOK, res)
		return
	}
	ctx.JSON(http.StatusOK, service.SearchUserByTags(ctx, tagNameList))
}

// UserRecommend todo
// @Tags        user
// @Summary     推荐用户
// @Description   推荐用户
// @Param pageNum query int true "页数"
// @Param pageSize query int true "每页大小"
// @Router /user/recommend [get]
func UserRecommend(ctx *gin.Context) {
	pageNum, pageSize := pageNumAndSize(ctx)
	data := service.UserRecommend(ctx, pageSize, pageNum)
	res := fmt.Sprintf("{ \"code\" : %s , \"data\" : %s , \"message\" : \"success\" , \"description\": \"\"}", "200", data.Data)
	ctx.Data(http.StatusOK, "application/json; charset=utf-8", []byte(res))
}

// UserUpdate
// @Tags        user
// @Summary     更新用户资料
// @Description   更新用户资料
// @Param User body model.User true "User"
// @Router /user/update [post]
func UserUpdate(ctx *gin.Context) {
	user := &model.User{}
	res := &response.BaseResponse{}
	err := parsePostJsonRequest(ctx, user)
	if err != nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		ctx.JSON(http.StatusOK, res)
		return
	}
	res = service.UpdateUser(ctx, user, service.GetUserCurrentInfo(ctx))
	ctx.JSON(http.StatusOK, res)
}

// UserDelete
// @Tags        user
// @Summary     删除人
// @Description   仅供管理员通过id
// @Param id body int true "User"
// @Router /user/delete [post]
func UserDelete(ctx *gin.Context) {
	var id int64
	res := &response.BaseResponse{}
	err := parsePostJsonRequest(ctx, id)
	if err != nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		ctx.JSON(http.StatusOK, res)
		return
	}
	if id <= 0 && !service.IsAdmin(ctx) {
		res.ResponseWithError(common.NO_AUTH, "无权限")
		ctx.JSON(http.StatusOK, res)
		return
	}

	db.GetMySQL().Model(&model.User{}).Update("isDelete", 1)
	ctx.JSON(http.StatusOK, res)
}

// UserMatch todo
// @Tags        user
// @Summary     获取匹配的用户
// @Description   区间 0 - 20  参数 num int64 需要登录
// @Param num query int true "获取匹配用户数量"
// @Router /user/match [get]
func UserMatch(ctx *gin.Context) {
	var num int64
	res := &response.BaseResponse{}
	err := parsePostJsonRequest(ctx, num)
	if err != nil {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		ctx.JSON(http.StatusOK, res)
		return
	}

	if num < 0 || num > 20 {
		res.ResponseWithError(common.PARAMS_ERROR, "参数错误")
		ctx.JSON(http.StatusOK, res)
		return
	}

	ctx.JSON(http.StatusOK, service.MatchUsers(ctx, num, service.GetUserCurrentInfo(ctx)))
}
